/* interrupt.c
 * By: Ariq Chowdhury
 * Date created: March 17th 2011
 * Date modified: March 17th 2011
 */

#include <interrupt.h>
#include <stdint.h>
#include <sys/io.h>

/* 
 * Init for Intel8259
 * Datasheet: http://pdos.csail.mit.edu/6.828/2005/readings/hardware/8259A.pdf
 */
void init_PIC()
{
  outb(ICW1, MASTER_PIC_COMMAND);
  outb(ICW1, SLAVE_PIC_COMMAND);
  outb(ICW2_M, MASTER_PIC_DATA);
  outb(ICW2_S, SLAVE_PIC_DATA); 
  outb(ICW3_M, MASTER_PIC_DATA);
  outb(ICW3_S, SLAVE_PIC_DATA);
  outb(ICW4, MASTER_PIC_DATA);
  outb(ICW4, SLAVE_PIC_DATA);

  outb(0xFF, MASTER_PIC_DATA);
  outb(0xFF, SLAVE_PIC_DATA);
  
}

/* Clear 8259 mask to enable interrupt */
void enable_interrupt(int_hook_t* hook)
{    
  uint8_t irq = hook->irq;
  uint16_t port;
  uint8_t value;
  
  if(irq < 8) {
    port = MASTER_PIC_DATA;
  }
  else {
    port = SLAVE_PIC_DATA;
    irq -= 8;
  }

  value = inb(port) & ~(1 << irq);
  outb(value, port);
}

/* Set 8259 mask to disable interrupt */
void disable_interrupt(int_hook_t* hook)
{    
  uint8_t irq = hook->irq;
  uint16_t port;
  uint8_t value;
  
  if(irq < 8) {
    port = MASTER_PIC_DATA;
  }
  else {
    port = SLAVE_PIC_DATA;
    irq -= 8;
  }

  value = inb(port) | (1 << irq);
  outb(value, port);
}

void set_int_handler(int_hook_t* hook, int irq, int_handler_t handler)
{
  if(irq < 0 || irq > NUM_INT_VECTORS) {
    ; /*Kernel Panic*/
  }

  hook->irq = irq;
  hook->handler = handler;
}

/* Send end of interrupt code to 8259 */
void eoi(int irq)
{
  uint8_t mask = 0x60 + irq;
  outb(mask, MASTER_PIC_COMMAND);
}


